1use super::list::{EnumScr, EscudeBinList, ListData, NameT};
3use super::ops::base::CustomOps;
4use crate::ext::io::*;
5use crate::scripts::base::*;
6use crate::types::*;
7use crate::utils::encoding::{decode_to_string, encode_string};
8use crate::utils::struct_pack::StructPack;
9use anyhow::Result;
10use int_enum::IntEnum;
11use std::collections::{BTreeSet, HashMap};
12use std::ffi::CString;
13use std::io::{Read, Seek, SeekFrom};
14use unicode_segmentation::UnicodeSegmentation;
15
16#[derive(Debug)]
17pub struct EscudeBinScriptBuilder {}
19
20impl EscudeBinScriptBuilder {
21 pub const fn new() -> Self {
23 EscudeBinScriptBuilder {}
24 }
25}
26
27impl ScriptBuilder for EscudeBinScriptBuilder {
28 fn default_encoding(&self) -> Encoding {
29 Encoding::Cp932
30 }
31
32 fn build_script(
33 &self,
34 data: Vec<u8>,
35 _filename: &str,
36 encoding: Encoding,
37 _archive_encoding: Encoding,
38 config: &ExtraConfig,
39 _archive: Option<&Box<dyn Script>>,
40 ) -> Result<Box<dyn Script>> {
41 Ok(Box::new(EscudeBinScript::new(data, encoding, config)?))
42 }
43
44 fn extensions(&self) -> &'static [&'static str] {
45 &["bin"]
46 }
47
48 fn script_type(&self) -> &'static ScriptType {
49 &ScriptType::Escude
50 }
51
52 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
53 if buf_len > 8 && buf.starts_with(b"ESCR1_00") {
54 return Some(255);
55 }
56 None
57 }
58}
59
60#[derive(Debug)]
61pub struct EscudeBinScript {
63 vms: Vec<u8>,
64 unk1: u32,
65 strings: Vec<String>,
66 names: Option<HashMap<usize, String>>,
67}
68
69fn load_enum_script(
70 filename: &str,
71 encoding: Encoding,
72 config: &ExtraConfig,
73) -> Result<Vec<NameT>> {
74 let buf = crate::utils::files::read_file(filename)?;
75 let scr = EscudeBinList::new(buf, filename, encoding, config)?;
76 for scr in scr.entries {
77 match scr.data {
78 ListData::Scr(scr) => match scr {
79 EnumScr::Names(names) => return Ok(names),
80 _ => {}
81 },
82 _ => {}
83 }
84 }
85 Err(anyhow::anyhow!(
86 "Failed to find name table in Escude enum script",
87 ))
88}
89
90impl EscudeBinScript {
91 pub fn new(data: Vec<u8>, encoding: Encoding, config: &ExtraConfig) -> Result<Self> {
97 let mut reader = MemReader::new(data);
98 let mut magic = [0u8; 8];
99 reader.read_exact(&mut magic)?;
100 if &magic != b"ESCR1_00" {
101 return Err(anyhow::anyhow!(
102 "Invalid Escude binary script magic: {:?}",
103 magic
104 ));
105 }
106 let string_count = reader.read_u32()?;
107 let mut offsets = Vec::with_capacity(string_count as usize);
108 for _ in 0..string_count {
109 offsets.push(reader.read_u32()?);
110 }
111 let vm_count = reader.read_u32()?;
112 let mut vms = Vec::with_capacity(vm_count as usize);
113 vms.resize(vm_count as usize, 0);
114 reader.read_exact(&mut vms)?;
115 let unk1 = reader.read_u32()?;
116 let mut strings = Vec::with_capacity(string_count as usize);
117 if encoding.is_jis() {
118 let replaces = StrReplacer::new()?;
119 for _ in 0..string_count {
120 let s = reader.read_cstring()?;
121 let s = replaces.replace(s.as_bytes())?;
122 strings.push(decode_to_string(encoding, &s, true)?);
123 }
124 } else {
125 for _ in 0..string_count {
126 let s = reader.read_cstring()?;
127 strings.push(decode_to_string(encoding, s.as_bytes(), true)?);
128 }
129 }
130 let names = match &config.escude_enum_scr {
131 Some(loc) => match load_enum_script(loc, encoding, config) {
132 Ok(list) => {
133 let mut names = HashMap::new();
134 let mut vm = VM::new(&vms);
135 vm.vars.insert(1, 1);
136 vm.vars.insert(132, 0);
137 vm.vars.insert(133, 0);
138 vm.vars.insert(134, 0);
139 vm.vars.insert(1001, 0);
140 vm.vars.insert(1003, 0);
141 for i in 135..140 {
142 vm.vars.insert(i, 1);
143 }
144 let _ = vm.run(Some(Box::new(super::ops::panicon::PaniconOps::new())));
145 for (index, name) in vm.names.iter() {
146 if let Some(name) = list.get(*name as usize) {
147 names.insert(*index as usize, name.text.clone());
148 }
149 }
150 Some(names)
151 }
152 Err(e) => {
153 eprintln!(
154 "WARN: Failed to load Escude enum script from {}: {}",
155 loc, e
156 );
157 crate::COUNTER.inc_warning();
158 None
159 }
160 },
161 None => None,
162 };
163 Ok(EscudeBinScript {
164 vms,
165 unk1,
166 strings,
167 names,
168 })
169 }
170}
171
172impl Script for EscudeBinScript {
173 fn default_output_script_type(&self) -> OutputScriptType {
174 OutputScriptType::Json
175 }
176
177 fn default_format_type(&self) -> FormatOptions {
178 FormatOptions::None
179 }
180
181 fn extract_messages(&self) -> Result<Vec<Message>> {
182 Ok(self
183 .strings
184 .iter()
185 .enumerate()
186 .map(|(i, s)| Message {
187 message: s.replace("<r>", "\n"),
188 name: self.names.as_ref().map(|n| n.get(&i).cloned()).flatten(),
189 })
190 .collect())
191 }
192
193 fn import_messages<'a>(
194 &'a self,
195 messages: Vec<Message>,
196 mut writer: Box<dyn WriteSeek + 'a>,
197 _filename: &str,
198 encoding: Encoding,
199 replacement: Option<&'a ReplacementTable>,
200 ) -> Result<()> {
201 writer.write_all(b"ESCR1_00")?;
202 let mut offsets = Vec::with_capacity(messages.len());
203 let mut strs = Vec::with_capacity(messages.len());
204 let mut len = 0;
205 for message in messages {
206 offsets.push(len);
207 let mut s = message.message.replace("\n", "<r>");
208 if let Some(repl) = replacement {
209 for (from, to) in &repl.map {
210 s = s.replace(from, to);
211 }
212 }
213 let encoded = encode_string(encoding, &s, false)?;
214 len += encoded.len() as u32 + 1;
215 strs.push(CString::new(encoded)?);
216 }
217 writer.write_u32(offsets.len() as u32)?;
218 offsets.pack(&mut writer, false, encoding)?;
219 writer.write_u32(self.vms.len() as u32)?;
220 writer.write_all(&self.vms)?;
221 writer.write_u32(self.unk1)?;
222 for s in strs {
223 writer.write_all(s.as_bytes_with_nul())?;
224 }
225 Ok(())
226 }
227
228 fn is_archive(&self) -> bool {
229 false
230 }
231}
232
233struct StrReplacer {
234 pub replacements: HashMap<Vec<u8>, Vec<u8>>,
235}
236
237enum JisStr {
238 Single(u8),
239 Double(u8, u8),
240}
241
242impl StrReplacer {
243 pub fn new() -> Result<Self> {
244 let mut s = StrReplacer {
245 replacements: HashMap::new(),
246 };
247 let half_width_katakana = "!? 。「」、…をぁぃぅぇぉゃゅょっーあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわん゛゜";
249 let mut bytes: Vec<u8> = (0xa0..=0xde).collect();
250 bytes.insert(0, 0x21);
251 bytes.insert(1, 0x3f);
252 s.add(&bytes, half_width_katakana)?;
253 Ok(s)
254 }
255
256 fn add(&mut self, from: &[u8], to: &str) -> Result<()> {
257 let encoding = Encoding::Cp932; let tos = UnicodeSegmentation::graphemes(to, true);
259 for (from, to) in from.into_iter().zip(tos) {
260 let from_bytes = vec![from.clone()];
261 let to_bytes = encode_string(encoding, to, true)?;
262 self.replacements.insert(from_bytes, to_bytes);
263 }
264 Ok(())
265 }
266
267 pub fn replace(&self, input: &[u8]) -> Result<Vec<u8>> {
268 let mut result = Vec::new();
269 let mut reader = MemReaderRef::new(input);
270 while let Ok(byte) = reader.read_u8() {
271 if byte < 0x80 || (byte >= 0xa0 && byte <= 0xdf) {
272 result.push(JisStr::Single(byte));
273 } else if (byte >= 0x81 && byte <= 0x9f) || (byte >= 0xe0 && byte <= 0xef) {
274 let next_byte = reader.read_u8()?;
275 if next_byte < 0x40 || next_byte > 0xfc {
276 return Err(anyhow::anyhow!("Invalid JIS encoding sequence"));
277 }
278 result.push(JisStr::Double(byte, next_byte));
279 } else {
280 return Err(anyhow::anyhow!("Invalid byte in JIS encoding: {}", byte));
281 }
282 }
283 let mut output = Vec::new();
284 for item in result {
285 match item {
286 JisStr::Single(byte) => {
287 let vec = vec![byte];
288 if let Some(replacement) = self.replacements.get(&vec) {
289 output.extend_from_slice(replacement);
290 } else {
291 output.push(byte);
292 }
293 }
294 JisStr::Double(byte1, byte2) => {
295 let key = vec![byte1, byte2];
296 if let Some(replacement) = self.replacements.get(&key) {
297 output.extend_from_slice(replacement);
298 } else {
299 output.push(byte1);
300 output.push(byte2);
301 }
302 }
303 }
304 }
305 Ok(output)
306 }
307}
308
309#[repr(u8)]
310#[derive(Debug, IntEnum)]
311enum BaseOp {
312 End,
313 Jump,
314 JumpZ,
315 Call,
316 Ret,
317 Push,
318 Pop,
319 Str,
320 SetVar,
321 GetVar,
322 SetFlag,
323 GetFlag,
324 Neg,
325 Add,
326 Sub,
327 Mul,
328 Div,
329 Mod,
330 Not,
331 And,
332 Or,
333 Xor,
334 Shr,
335 Shl,
336 Eq,
337 Ne,
338 Gt,
339 Ge,
340 Lt,
341 Le,
342 LNot,
343 LAnd,
344 LOr,
345 FileLine,
346}
347
348pub(crate) trait ReadParam<T> {
349 fn read_param(&mut self) -> Result<T>;
350}
351
352#[derive(Debug)]
353pub(crate) struct VM<'a, T: std::fmt::Debug> {
354 pub reader: MemReaderRef<'a>,
355 pub data: Vec<T>,
356 pub stack: Vec<u64>,
357 pub strs: Vec<T>,
358 pub vars: HashMap<T, T>,
359 pub flags: HashMap<T, bool>,
360 pub mess: BTreeSet<T>,
361 pub names: HashMap<T, T>,
362}
363
364impl ReadParam<i32> for MemReaderRef<'_> {
365 fn read_param(&mut self) -> Result<i32> {
366 Ok(self.read_i32()?)
367 }
368}
369
370impl<'a, T> VM<'a, T>
371where
372 MemReaderRef<'a>: ReadParam<T>,
373 T: TryInto<u64>
374 + Default
375 + Eq
376 + Ord
377 + Copy
378 + std::fmt::Debug
379 + std::fmt::Display
380 + std::hash::Hash
381 + From<u8>
382 + std::ops::Neg<Output = T>
383 + std::ops::Add<Output = T>
384 + std::ops::Sub<Output = T>
385 + std::ops::Mul<Output = T>
386 + std::ops::Div<Output = T>
387 + std::ops::Rem<Output = T>
388 + std::ops::Not<Output = T>
389 + std::ops::BitAnd<Output = T>
390 + std::ops::BitOr<Output = T>
391 + std::ops::BitXor<Output = T>
392 + std::ops::Shr<Output = T>
393 + std::ops::Shl<Output = T>,
394 anyhow::Error: From<<T as TryInto<u64>>::Error>,
395{
396 pub fn new(data: &'a [u8]) -> Self {
397 VM {
398 reader: MemReaderRef::new(data),
399 data: Vec::new(),
400 stack: Vec::new(),
401 strs: Vec::new(),
402 vars: HashMap::new(),
403 flags: HashMap::new(),
404 mess: BTreeSet::new(),
405 names: HashMap::new(),
406 }
407 }
408
409 pub fn pop_data(&mut self) -> Result<T> {
410 self.data
411 .pop()
412 .ok_or_else(|| anyhow::anyhow!("No data to pop"))
413 }
414
415 fn pop_stack(&mut self) -> Result<u64> {
416 self.stack
417 .pop()
418 .ok_or_else(|| anyhow::anyhow!("No stack to pop"))
419 }
420
421 pub fn run(&mut self, mut custom_ops: Option<Box<dyn CustomOps<T>>>) -> Result<()> {
422 loop {
423 if self.reader.is_eof() {
424 break;
425 }
426 let op = self.reader.read_u8()?;
427 if let Ok(op) = BaseOp::try_from(op) {
428 match op {
430 BaseOp::End => break,
431 BaseOp::Jump => {
432 let offset: T = self.reader.read_param()?;
433 let offset: u64 = offset.try_into()?;
434 self.reader.seek(SeekFrom::Start(offset))?;
435 }
436 BaseOp::JumpZ => {
437 let offset: T = self.reader.read_param()?;
438 let offset: u64 = offset.try_into()?;
439 if self.pop_data()? == Default::default() {
440 self.reader.seek(SeekFrom::Start(offset))?;
441 }
442 }
443 BaseOp::Call => {
444 let offset: T = self.reader.read_param()?;
445 let offset: u64 = offset.try_into()?;
446 let pos = self.reader.stream_position()?;
447 self.stack.push(pos);
448 self.reader.seek(SeekFrom::Start(offset))?;
449 }
450 BaseOp::Ret => {
451 if self.stack.is_empty() {
452 let code = self.reader.read_u8()?;
453 if code == 0 && self.reader.is_eof() {
454 break;
455 }
456 }
457 let stack = self.pop_stack()?;
458 self.reader.seek(SeekFrom::Start(stack))?;
459 }
460 BaseOp::Push => {
461 let d = self.reader.read_param()?;
462 self.data.push(d);
463 }
464 BaseOp::Pop => {
465 self.pop_data()?;
466 }
467 BaseOp::Str => {
468 let param = self.reader.read_param()?;
469 self.strs.push(param);
470 self.data.push(param);
471 }
472 BaseOp::SetVar => {
473 let value = self.pop_data()?;
474 let index = self.pop_data()?;
475 self.vars.insert(index, value);
476 self.data.push(value);
477 }
478 BaseOp::GetVar => {
479 let index = self.pop_data()?;
480 let value = self
481 .vars
482 .get(&index)
483 .ok_or_else(|| anyhow::anyhow!("Variable not found: {}", index))?;
484 self.data.push(*value);
485 }
486 BaseOp::SetFlag => {
487 let value = self.pop_data()?;
488 let index = self.pop_data()?;
489 let flag = value != Default::default();
490 self.flags.insert(index, flag);
491 self.data.push(value);
492 }
493 BaseOp::GetFlag => {
494 let index = self.pop_data()?;
495 let flag = self.flags.get(&index).cloned().unwrap_or(false);
496 self.data
497 .push(if flag { T::from(1u8) } else { T::from(0u8) });
498 }
499 BaseOp::Neg => {
500 let value = -self.pop_data()?;
501 self.data.push(value);
502 }
503 BaseOp::Add => {
504 let b = self.pop_data()?;
505 let a = self.pop_data()?;
506 self.data.push(a + b);
507 }
508 BaseOp::Sub => {
509 let b = self.pop_data()?;
510 let a = self.pop_data()?;
511 self.data.push(a - b);
512 }
513 BaseOp::Mul => {
514 let b = self.pop_data()?;
515 let a = self.pop_data()?;
516 self.data.push(a * b);
517 }
518 BaseOp::Div => {
519 let b = self.pop_data()?;
520 if b == Default::default() {
521 return Err(anyhow::anyhow!("Division by zero"));
522 }
523 let a = self.pop_data()?;
524 self.data.push(a / b);
525 }
526 BaseOp::Mod => {
527 let b = self.pop_data()?;
528 if b == Default::default() {
529 return Err(anyhow::anyhow!("Division by zero"));
530 }
531 let a = self.pop_data()?;
532 self.data.push(a % b);
533 }
534 BaseOp::Not => {
535 let value = self.pop_data()?;
536 self.data.push(!value);
537 }
538 BaseOp::And => {
539 let b = self.pop_data()?;
540 let a = self.pop_data()?;
541 self.data.push(a & b);
542 }
543 BaseOp::Or => {
544 let b = self.pop_data()?;
545 let a = self.pop_data()?;
546 self.data.push(a | b);
547 }
548 BaseOp::Xor => {
549 let b = self.pop_data()?;
550 let a = self.pop_data()?;
551 self.data.push(a ^ b);
552 }
553 BaseOp::Shr => {
554 let b = self.pop_data()?;
555 let a = self.pop_data()?;
556 self.data.push(a >> b);
557 }
558 BaseOp::Shl => {
559 let b = self.pop_data()?;
560 let a = self.pop_data()?;
561 self.data.push(a << b);
562 }
563 BaseOp::Eq => {
564 let b = self.pop_data()?;
565 let a = self.pop_data()?;
566 self.data
567 .push(if a == b { T::from(1u8) } else { T::from(0u8) });
568 }
569 BaseOp::Ne => {
570 let b = self.pop_data()?;
571 let a = self.pop_data()?;
572 self.data
573 .push(if a != b { T::from(1u8) } else { T::from(0u8) });
574 }
575 BaseOp::Gt => {
577 let a = self.pop_data()?;
578 let b = self.pop_data()?;
579 self.data
580 .push(if a > b { T::from(1u8) } else { T::from(0u8) });
581 }
582 BaseOp::Ge => {
583 let a = self.pop_data()?;
584 let b = self.pop_data()?;
585 self.data
586 .push(if a >= b { T::from(1u8) } else { T::from(0u8) });
587 }
588 BaseOp::Lt => {
589 let a = self.pop_data()?;
590 let b = self.pop_data()?;
591 self.data
592 .push(if a < b { T::from(1u8) } else { T::from(0u8) });
593 }
594 BaseOp::Le => {
595 let a = self.pop_data()?;
596 let b = self.pop_data()?;
597 self.data
598 .push(if a <= b { T::from(1u8) } else { T::from(0u8) });
599 }
600 BaseOp::LNot => {
601 let value = self.pop_data()?;
602 self.data.push(if value == Default::default() {
603 T::from(1u8)
604 } else {
605 T::from(0u8)
606 });
607 }
608 BaseOp::LAnd => {
609 let b = self.pop_data()? != Default::default();
610 let a = self.pop_data()? != Default::default();
611 self.data
612 .push(if a && b { T::from(1u8) } else { T::from(0u8) });
613 }
614 BaseOp::LOr => {
615 let b = self.pop_data()? != Default::default();
616 let a = self.pop_data()? != Default::default();
617 self.data
618 .push(if a || b { T::from(1u8) } else { T::from(0u8) });
619 }
620 BaseOp::FileLine => {
621 let _: T = self.reader.read_param()?;
622 }
623 }
624 continue;
625 }
626 if let Some(ops) = &mut custom_ops {
627 let nbreak = ops.run(self, op)?;
628 if nbreak {
629 break;
630 }
631 } else {
632 return Err(anyhow::anyhow!("Unknown operation: {}", op));
633 }
634 }
635 Ok(())
636 }
637
638 pub fn skip_n_params(&mut self, n: u64, nbreak: bool) -> Result<bool> {
639 for _ in 0..n {
640 self.pop_data()?;
641 }
642 Ok(nbreak)
643 }
644
645 pub fn skip_params(&mut self, nbreak: bool) -> Result<bool> {
646 let count: T = self.reader.read_param()?;
647 let count: u64 = count.try_into()?;
648 self.skip_n_params(count, nbreak)
649 }
650
651 pub fn read_params(&mut self, ncount: Option<u64>) -> Result<Vec<T>> {
652 let count = match ncount {
653 Some(count) => count,
654 None => {
655 let count: T = self.reader.read_param()?;
656 count.try_into()?
657 }
658 };
659 let data_len = self.data.len();
660 if (data_len as u64) < count {
661 return Err(anyhow::anyhow!(
662 "Not enough data to read {} parameters, only {} parameters available",
663 count,
664 data_len
665 ));
666 }
667 let mut params = Vec::with_capacity(count as usize);
668 params.resize(count as usize, Default::default());
669 params.copy_from_slice(&self.data[data_len - count as usize..]);
670 self.data.truncate(data_len - count as usize);
671 Ok(params)
672 }
673}